package com.snake.springboot.custom.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.snake.common.utils.IPToolsUtlis;
import org.snake.common.utils.RandomUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * AOP 切面记录接口调用情况
 */
@Component
@Aspect
public class ControllerAspect {
    private static final Logger logger = LoggerFactory.getLogger(ControllerAspect.class);
    @Value("${log.trace.key:zTraceId}")
    private String keyTraceId;
    private final static long timeOut=10000;
    private final static int maxWith=3000;
    private ApplicationContext applicationContext;
    @Autowired
    public ControllerAspect(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Pointcut("@within(org.springframework.web.bind.annotation.RestController)"
			+ "|| @within(org.springframework.stereotype.Controller)")
	public void apiController() {}

    @Around("apiController()")
    public Object handleControllerMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        MDC.put(keyTraceId, RandomUtils.charNum(6));
        long mark = System.currentTimeMillis();
        //原始的HTTP请求和响应的信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //获取参数
        Object[] objects = proceedingJoinPoint.getArgs();
        //获取参数
        Object[] arguments  = new Object[objects.length];
        for (int i = 0; i < objects.length; i++) {
            if (objects[i] instanceof ServletRequest || objects[i] instanceof ServletResponse || objects[i] instanceof MultipartFile) {
                //过滤掉不能序列化的参数
                continue;
            }
            arguments[i] = objects[i];
        }
        String params = JSON.toJSONString(arguments);
        logger.info(String.format("[request %s U:%s IP:%s URI:%s Params:%s]",request.getHeader("urlFrom"),getUser(), IPToolsUtlis.getIpAddr(request),request.getRequestURI(), StringUtils.abbreviate(params, maxWith)));

        //获取返回对象
        Object object = proceedingJoinPoint.proceed();
        String result = JSONObject.toJSONString(object);

        long time = System.currentTimeMillis() - mark;
        if (time>timeOut){
       //     applicationContext.publishEvent(new TimeOutEvent(this,time));
        }
        logger.info(String.format("[response U:%s URI:%s Time:%s Result:%s]",getUser(),request.getRequestURI(),time, StringUtils.abbreviate(result, maxWith)));
        return object;
    }

    public static String getIpAddress(HttpServletRequest request) {
        String unknown = "unknown";
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip!=null){
            return ip.split(",")[0];
        }
        return null;
    }

    public String getUser(){
//        AccountInfoModel model = LoginUser.orNullUser();
//        if (model!=null){
//            return model.getName();
//        }
        return "无";

    }
}
